package xworker;

import com.gluonhq.attach.storage.StorageService;
import com.gluonhq.charm.glisten.application.AppManager;
import com.gluonhq.charm.glisten.mvc.View;
import com.gluonhq.charm.glisten.visual.Swatch;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.xmeta.ActionContext;
import org.xmeta.Thing;
import org.xmeta.World;
import xworker.gluon.glisten.application.ThingApplication;
import xworker.gluon.xapp.IApp;
import xworker.gluon.xapp.XApp;
import xworker.lang.executor.Executor;

import java.io.File;
import java.util.Optional;

public class XWorkerApplication extends Application implements IApp {
    private static final String TAG = xworker.XWorkerApplication.class.getName();

    private final AppManager appManager = AppManager.initialize(this::postInit);
    private final ActionContext actionContext = new ActionContext();
    private ThingApplication thingApplication;

    public ActionContext getActionContext() {
        return actionContext;
    }

    public void init() throws Exception {
        XApp.setApp(this);
        JavaActionRegister.regist();

        //appManager.addViewFactory(HOME_VIEW, () -> new View() {});
        try {
            File rootFile;
            Optional<StorageService> storageService = StorageService.create();
            if(storageService.isPresent()){
                try {
                    Optional<File> rootFileOp = storageService.get().getPrivateStorage();
                    rootFile = rootFileOp.orElseGet(() -> new File("./"));
                }catch(Exception ignored){
                    rootFile = new File("./");
                }
            }else{
                rootFile = new File("./");
            }

            if(rootFile.exists()){
                World world = World.getInstance();
                world.init(rootFile.getPath() + "/xworker/");

                Thing app = world.getThing("xworker.gluon.xapp.XWorkerApplication");
                if (app != null) {
                    BuilderFactoryRegister.regist();

                    setAppManager(app);
                } else {
                    VBox root = new VBox();
                    TextArea textArea = new TextArea();
                    VBox.setVgrow(textArea, Priority.ALWAYS);
                    root.getChildren().add(textArea);

                    StringBuilder msg = new StringBuilder("NO app manager!\n" + "XWorker home:\n" +
                            world.getPath() + "\n" +
                            "Application:\n" +
                            "xworker.gluon.xapp.XWorkerApplication\n");
                    msg.append("Class path:\n");
                    for(String path : world.getClassLoader().getAlClassPathDirs()){
                        msg.append(path).append("\n");
                    }
                    msg.append("Test things: \n");
                    msg.append("xworker.lang.Configuration=").append(world.getThing("xworker.lang.Configuration")).append("\n");
                    msg.append("xworker.lang.Menu=").append(world.getThing("xworker.lang.Menu")).append("\n");
                    msg.append("xworker/lang/Configuration.dml=").append(world.getResource("xworker/lang/Configuration.dml")).append("\n");
                    msg.append("xworker/lang/Menu.xer.txt=").append(world.getResource("xworker/lang/Menu.xer.txt")).append("\n");
                    msg.append("/xworker/lang/Configuration.dml=").append(world.getResource("/xworker/lang/Configuration.dml")).append("\n");
                    msg.append("/xworker/lang/Menu.xer.txt=").append(world.getResource("/xworker/lang/Menu.xer.txt")).append("\n");
                    msg.append("this:xworker/lang/Configuration.dml=").append(XWorkerApplication.class.getResource("xworker/lang/Configuration.dml")).append("\n");
                    msg.append("this:xworker/lang/Menu.xer.txt=").append(XWorkerApplication.class.getResource("xworker/lang/Menu.xer.txt")).append("\n");
                    msg.append("this:/xworker/lang/Configuration.dml=").append(XWorkerApplication.class.getResource("/xworker/lang/Configuration.dml")).append("\n");
                    msg.append("this:/xworker/lang/Menu.xer.txt=").append(XWorkerApplication.class.getResource("/xworker/lang/Menu.xer.txt")).append("\n");
                    msg.append("this:primary.fxml=").append(XWorkerApplication.class.getResource("primary.fxml")).append("\n");
                    msg.append("this:/xworker/primary.fxml=").append(XWorkerApplication.class.getResource("/xworker/primary.fxml")).append("\n");
                    msg.append("this:primary.dml=").append(XWorkerApplication.class.getResource("primary.dml")).append("\n");
                    msg.append("this:/xworker/primary.dml=").append(XWorkerApplication.class.getResource("/xworker/primary.dml")).append("\n");

                    textArea.setText(msg.toString());
                    appManager.addViewFactory(AppManager.HOME_VIEW, () -> new View(root));
                }
            }else{
                appManager.addViewFactory(AppManager.HOME_VIEW, () -> new View(new Label("Cat not locate root file")));
            }
        } catch (Exception e) {
            appManager.addViewFactory(AppManager.HOME_VIEW, () -> new View(new Label(e.getMessage())));
        }
    }

    public void setAppManager(Thing appManager){
        Executor.info(TAG, "Init thing manager, path=" + appManager.getMetadata().getPath());
        ThingApplication thingApplication = new ThingApplication(appManager, actionContext);
        thingApplication.init();

        this.thingApplication = thingApplication;
    }

    public void start(Stage primaryStage) throws Exception {
        try {
            appManager.start(primaryStage);
            primaryStage.setWidth(540);
            primaryStage.setHeight(960);

            if(thingApplication != null && thingApplication.getTitle() != null){
                appManager.setTitle(thingApplication.getTitle());
            }
        }catch(Exception e){
            Executor.info(TAG, "Start error", e);
        }
    }

    private void postInit(Scene scene) {
        Swatch.BLUE.assignTo(scene);
    }

    public static void main(String[] args){
        launch(args);
    }
}
